#pragma once
#include <iostream>
#include <memory>
#include <string>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <cstring>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "myErr.hpp"
#include <functional>
#include "ringQueue.hpp"
#include "Thread.hpp"
#include "myLockGuard.hpp"
#include <pthread.h>
#include <unordered_map>
#include <vector>
using namespace std;
// using func_t=function<string(string&)>;
using func_t = std::function<string(std::string &)>;

static uint16_t default_port = 8888;

class udp_sever
{
public:
    // udp_sever(func_t severice, uint16_t port=default_port)
    udp_sever(uint16_t port = default_port)
        : port_(port)
    {
        p=new Thread(1,bind(&udp_sever::Rec,this));
        c=new Thread(1,bind(&udp_sever::Send,this));
        pthread_mutex_init(&lock_,nullptr);
        //rq=new ringQueue<string>(5);//环形队列
        std::cout << "server addr: " << port_ << std::endl;
    }
    void Start()
    {
        sock_ = socket(AF_INET, SOCK_DGRAM, 0); // 创建套接字
        if (sock_ < 0)
        {
            cerr << "创建失败！" << strerror(errno) << endl;
            exit(SOCKET_ERR);
        }
        // cout<<"ip_: "<<ip_<<" port_: "<<port_<<endl;
        struct sockaddr_in local;
        bzero(&local, sizeof(local));  // 初始化结构体，方便重新赋值
        local.sin_family = AF_INET;    // 进行网络通信
        local.sin_port = htons(port_); // 转换成网络字节序
        local.sin_addr.s_addr = INADDR_ANY;
        // int bindRet=bind(sock_,(sockaddr*)&local,sizeof(local));//把套接字绑定到网络上
        if (bind(sock_, (sockaddr *)&local, sizeof(local)) < 0)
        {
            cerr << "绑定失败！: " << strerror(errno) << endl;
            exit(BIND_ERR);
        }
        cout << "绑定成功，可以开始通信！" << endl;
        p->run();
        c->run();
    }
    void addUser(string& name,struct sockaddr_in peer)
    {
        //myLockGuard lockguard(&lock_);

        onlineUser[name]=peer;
        cout<<"构建用户成功！"<<endl;
    }
    void Rec()
    {
        char buf[2048]; // 存放接收客户端发送信息的缓冲区

        while (1)
        {
            struct sockaddr_in peer; // 存放接收的客户端的ip和端口信息
            socklen_t len = sizeof(peer);
            int n = recvfrom(sock_, buf, sizeof(buf) - 1, 0, (struct sockaddr*)&peer, &len);
            if (n < 0)
            {
                cout<<"1"<<endl;
                continue;
            } // 没收到信息，继续循环
            buf[n]=0;
            string name;
            string cilentIp=inet_ntoa(peer.sin_addr);
            uint16_t cilentPort=ntohs(peer.sin_port);
            std::string clientip = inet_ntoa(peer.sin_addr);
            cout<<cilentIp<<" - "<<cilentPort<<" # "<<buf<<"测试用的"<<endl;
            //构建用户
            name=cilentIp;
            name+='-';
            name+=cilentPort;
            addUser(name,peer);
            cout<<"2"<<endl;
            string message=buf;
            rq.push(message);
            cout<<"push is sucess!"<<endl;

        }
    }
    void Send()
    {
        string MS;
        rq.pop(MS);
        vector<struct sockaddr_in>vs;
        for(auto &x:onlineUser)
        {
            vs.push_back(x.second);
        }
        for(auto x:vs)
        {
            sendto(sock_,MS.c_str(),MS.size(),0,(struct sockaddr*)&(x),sizeof(struct sockaddr));
        }

    }

    // void Start()
    // {
    //     //收
    //     char buf[2048]={0};//缓冲区
    //     while(1)//服务器不会停止，需要死循环
    //     {
    //         struct sockaddr_in peer;//存放远端的ip和端口等信息
    //         socklen_t len=sizeof(peer);//接受数据大小
    //         int n=recvfrom(sock_,buf,sizeof(buf)-1,0,(struct sockaddr*)&peer,&len);
    //         if(n>0)
    //         {
    //             buf[n]=0;
    //             //cout<<"This is receive from udp_cilent: "<<buf<<endl;
    //         }
    //         else
    //             continue;
    //         // string cilentIp=inet_ntoa(peer.sin_addr);
    //         // uint16_t cilentPort=ntohs(peer.sin_port);
    //         string messages=buf;
    //         string resp=severice_(messages);
    //         //cout<<"测试："<<messages<<endl;
    //         sendto(sock_,resp.c_str(),resp.size(),0,(struct sockaddr*)&peer,sizeof(peer));
    //     }
    //}
    ~udp_sever()
    {
        pthread_mutex_destroy(&lock_);
        p->join();
        c->join();
    }

private:
    int sock_;
    uint16_t port_;
    // func_t severice_;
    pthread_mutex_t lock_;
    Thread *p; // 生产者线程
    Thread *c; // 消费者线程
    ringQueue<string> rq;
    unordered_map<string, struct sockaddr_in> onlineUser; // 标识线上用户
    // std::unordered_map<std::string, struct sockaddr_in> onlineuser;
};